////
/// @group slider
////

@use "../utils";
@use "../border-radius";
@use "../theme/colors";
@use "../theme/theme";
@use "../icon/icon";
@use "../tooltip/tooltip";
@use "../transition/transition";
@use "base";

/// Set to `true` to disable the `Slider` styles.
/// @type Boolean
$disable-everything: base.$form-disable-everything !default;

/// Set to `true` to disable the horizontal `Slider` styles.
/// @type Boolean
$disable-horizontal: $disable-everything !default;

/// Set to `true` to disable the vertical `Slider` styles.
/// @type Boolean
$disable-vertical: $disable-everything !default;

/// Set to `true` to disable the two-thumb `Slider` styles.
/// @type Boolean
$disable-range: $disable-everything !default;

/// Set to `true` to disable the `Slider` styles show the current value in a
/// tooltip.
/// @type Boolean
$disable-discrete: $disable-everything !default;

/// Set to `true` to disable the `Slider` styles that show the tick marks below
/// the slider track.
/// @type Boolean
$disable-discrete-marks: $disable-discrete !default;

/// Set to `true` to disable the `Slider` styles that display a label with each
/// tick mark below the slider track.
/// @type Boolean
$disable-discrete-marks-labels: $disable-discrete-marks !default;

/// The `height` of the `Slider`'s track while horizontal or the `width` while
/// vertical.
///
/// @type Number
$size: 2rem !default;

/// The default `height` for a vertical `Slider`.
/// @type Number
$vertical-size: 15rem !default;

/// The default color for a `Slider` and is applied to:
/// - The Slider "thumb",
/// - The active slider track
/// - The inactive slider track (with opacity applied)
///
/// If more color customization is required, set this to `null` and configure
/// the `$track-active-color`, `$track-active-opacity`,
/// `$track-inactive-color`, and `$track-inactive-opacity`
/// instead.
///
/// @see $track-active-color
/// @see $track-active-opacity
/// @see $track-inactive-color
/// @see $track-inactive-opacity
/// @type Color
$track-color: theme.theme-get-var(primary-color) !default;

/// The height/width of the `Slider` track representing the current value. This
/// should normally be greater than or equal to the `$size`.
///
/// @see $size
/// @type Number
$track-active-size: 0.375rem !default;

/// Set this value if additional control is required or the `Slider` active
/// color.
///
/// @see $track-color
/// @type Color
$track-active-color: null !default;

/// An optional opacity value to apply to the active `Slider` color.
///
/// @see $track-color
/// @type Color
$track-active-opacity: null !default;

/// The `z-index` for the active `Slider` track. This normally shouldn't need
/// to be changed but should be greater than the
/// `$track-inactive-z-index`.
///
/// @see $track-inactive-z-index
/// @type Number
$track-active-z-index: 2 !default;

/// The height/width for the inactive `Slider` track.
///
/// @type Number
$track-inactive-size: 0.25rem !default;

/// Set this value if additional control is required or the `Slider` inactive
/// color.
///
/// @see $track-color
/// @type Number
$track-inactive-color: null !default;

/// The opacity to apply to the `Slider` inactive track background color.
///
/// @see $track-color
/// @type Number
$track-inactive-opacity: 0.5 !default;

/// The `z-index` for the inactive `Slider` track. This normally shouldn't need
/// to be changed but should be less than the `$track-active-z-index`
///
/// @see $track-active-z-index
/// @type Number
$track-inactive-z-index: 1 !default;

/// The background-color to apply to a `Slider` track while disabled.
///
/// @type Color
$track-disabled-color: theme.theme-get-var(text-disabled-color) !default;

/// The default height of a discrete `Slider` tick mark.
/// @type Number
$mark-height: $track-inactive-size !default;

/// The default width of a discrete `Slider` tick mark.
/// @type Number
$mark-width: $track-inactive-size !default;

/// The default border-radius for a discrete `Slider` tick mark.
/// @type Number
$mark-border-radius: border-radius.get-var(full) !default;

/// The light theme `Slider` tick mark color.
/// @type Color
$mark-light-active-color: theme.theme-get-var(on-primary-color) !default;

/// The dark theme `Slider` tick mark color.
/// @type Color
$mark-dark-active-color: $mark-light-active-color !default;

/// The light theme `Slider` tick mark opacity.
/// @type Number
$mark-light-active-opacity: 0.38 !default;

/// The dark theme `Slider` tick mark opacity.
/// @type Number
$mark-dark-active-opacity: 0.38 !default;

/// The default `Slider` tick mark color.
/// @type Color
$mark-active-color: theme.get-default-color(
  $mark-light-active-color,
  $mark-dark-active-color
) !default;

/// The default `Slider` tick mark opacity.
/// @type Number
$mark-active-opacity: theme.get-default-color(
  $mark-light-active-opacity,
  $mark-dark-active-opacity
) !default;

/// The light theme color for a `Slider` mark that is not covered by the active
/// `Slider` track.
/// @type Color
$mark-light-inactive-color: colors.$black !default;

/// The dark theme color for a `Slider` mark that is not covered by the active
/// `Slider` track.
/// @type Color
$mark-dark-inactive-color: colors.$white !default;

/// The default color for a `Slider` mark that is not covered by the active
/// `Slider` track.
///
/// @type Color
$mark-inactive-color: theme.get-default-color(
  $mark-light-inactive-color,
  $mark-dark-inactive-color
) !default;

/// The default opacity to apply to the light theme `Slider` mark.
/// @type Number
$mark-light-inactive-opacity: 1 !default;

/// The default opacity to apply to the dark theme `Slider` mark.
/// @type Number
$mark-dark-inactive-opacity: 0.8 !default;

/// The default opacity to apply to the `Slider` mark.
/// @type Number
$mark-inactive-opacity: theme.get-default-color(
  $mark-light-inactive-opacity,
  $mark-dark-inactive-opacity
) !default;

/// The z-index for an inactive `Slider` mark.
/// @type Number
$mark-inactive-z-index: 1 !default;

/// The z-index for an active `Slider` mark.
/// @type Number
$mark-active-z-index: $track-active-z-index + 1 !default;

/// The size for the `Slider` thumb.
/// @type Number
$thumb-size: 1.25rem !default;

/// The `border-radius` for the `Slider` thumb.
/// @type Number
$thumb-border-radius: border-radius.get-var(full) !default;

/// The amount of opacity to apply to the focused/active state of the `Slider`
/// thumb.
///
/// @see $thumb-focus-scale
/// @see $thumb-active-scale
/// @type Number
$thumb-bubble-opacity: 0.3 !default;

/// The `z-index` for the `Slider` thumb.
/// @type Number
$thumb-z-index: $track-active-z-index !default;

/// The size of the focused state for a `Slider` thumb.
///
/// @see $thumb-bubble-opacity
/// @type Number
$thumb-focus-scale: 2 !default;

/// The size of the active state for a `Slider` thumb.
///
/// @see $thumb-bubble-opacity
/// @type Number
$thumb-active-scale: 2.5 !default;

/// The size of a disabled `Slider` thumb.
///
/// @see $thumb-mask-scale
/// @type Number
$thumb-disabled-scale: 0.5 !default;

/// The size of a disabled `Slider` thumb which is used to apply the spacing
/// between the track and thumb. This should be larger than the
/// `$thumb-disabled-scale`
///
/// @see $thumb-disabled-scale
/// @type Number
$thumb-mask-scale: 0.8 !default;

/// The disabled color for a `Slider` thumb.
/// @type Color
$thumb-disabled-color: $track-disabled-color !default;

/// The discrete `Slider` tooltip caret size which is generated using `border`.
/// @type Number
$tooltip-caret-size: 0.3rem !default;

/// The top/left for the discrete `Slider` tooltip.
/// @type Number
$tooltip-offset: calc(-1 * ($thumb-size + icon.$spacing)) !default;

/// The `z-index` for the discrete `Slider` tooltip.
/// @type Number
$tooltip-z-index: 0 !default;

/// The amount of padding to apply around the `Slider` component and also the
/// "touch" area for the `Slider`. This should generally be at least 1/2 the
/// `$thumb-size` so it does not overlap other elements.
///
/// @type Number
$container-padding: $thumb-size * 0.5 !default;

/// The amount of spacing between a `Slider` addon and the `SliderTrack`.
/// @type Number
$container-addon-spacing: $thumb-size !default;

/// The `transition-duration` to apply to the `Slider` while the next value
/// should animate.
/// @type Number
$transition-duration: transition.$linear-duration !default;

/// The `transition-timing-function` to apply to the `Slider` while the next
/// value should animate.
/// @type Number
$transition-timing-function: transition.$linear-timing-function !default;

/// The available configurable css variables and mostly used internally for the
/// `get-var`, `set-var`, and `use-var` utils.
/// @type List
$variables: (
  color,
  active-color,
  inactive-color,
  size,
  active-size,
  inactive-size,
  vertical-size,
  offset-1,
  offset-2,
  tooltip-scale,
  tooltip-translate,
  mark-offset,
  mark-active-color,
  mark-active-opacity,
  mark-inactive-color,
  mark-inactive-opacity
);

/// @param {String} name - The supported variable name
/// @param {any} fallback [null] - An optional fallback value
/// @returns {String} a `var()` statement
@function get-var($name, $fallback: null) {
  $var: utils.get-var-name($variables, $name, "slider");
  @if $fallback {
    @return var(#{$var}, #{$fallback});
  }

  @return var(#{$var});
}

/// @param {String} name - The supported variable name
/// @param {any} value - The value to set the variable to. Supports `null` which
/// will just be a no-op.
@mixin set-var($name, $value) {
  @if $value {
    #{utils.get-var-name($variables, $name, "slider")}: #{$value};
  }
}

/// @param {String} property - The css property to apply the variable to
/// @param {String} name [$property] - The supported variable name
/// @param {any} fallback [null] - An optional fallback value if the variable
/// has not been set
@mixin use-var($property, $name: $property, $fallback: null) {
  #{$property}: get-var($name, $fallback);
}

/// Applies the light the variables based on feature flags
@mixin use-light-theme {
  @if not $disable-everything and not $disable-discrete-marks {
    @if $mark-light-active-color and
      $mark-light-active-color !=
      $mark-dark-active-color
    {
      @include set-var(mark-active-color, $mark-light-active-color);
    }

    @if $mark-light-inactive-color and
      $mark-light-inactive-color !=
      $mark-dark-inactive-color
    {
      @include set-var(mark-inactive-color, $mark-light-inactive-color);
    }
    @if $mark-light-inactive-opacity and
      $mark-light-inactive-opacity !=
      $mark-dark-inactive-opacity
    {
      @include set-var(mark-inactive-opacity, $mark-light-inactive-opacity);
    }
  }
}

/// Applies the dark the variables based on feature flags
@mixin use-dark-theme {
  @if not $disable-everything and not $disable-discrete-marks {
    @if $mark-dark-active-color and
      $mark-light-active-color !=
      $mark-dark-active-color
    {
      @include set-var(mark-active-color, $mark-dark-active-color);
    }

    @if $mark-dark-inactive-color and
      $mark-light-inactive-color !=
      $mark-dark-inactive-color
    {
      @include set-var(mark-inactive-color, $mark-dark-inactive-color);
    }
    @if $mark-dark-inactive-opacity and
      $mark-light-inactive-opacity !=
      $mark-dark-inactive-opacity
    {
      @include set-var(mark-inactive-opacity, $mark-dark-inactive-opacity);
    }
  }
}

/// Conditionally applies the css variables based on feature flags
@mixin variables {
  @if not $disable-everything {
    @if not theme.is-theme-color-var($track-color) {
      @include set-var(color, $track-color);
    }
    @include set-var(active-color, $track-active-color);
    @include set-var(inactive-color, $track-inactive-color);
    @include set-var(size, $size);
    @include set-var(active-size, $track-active-size);
    @include set-var(inactive-size, $track-inactive-size);
    @if not $disable-discrete {
      @include set-var(tooltip-scale, 1);
      @include set-var(tooltip-translate, -50%);

      @if not $disable-discrete-marks {
        @include set-var(mark-offset, 0%);
        @include set-var(mark-active-color, $mark-active-color);
        @include set-var(mark-active-opacity, $mark-active-opacity);
        @include set-var(mark-inactive-color, $mark-inactive-color);
        @include set-var(mark-inactive-opacity, $mark-inactive-opacity);
      }
    }

    @if not $disable-vertical {
      @include set-var(vertical-size, $vertical-size);
    }
  }
}

/// Generates all the styles based on feature flags.
///
/// @param {Boolean} disable-layer [false] - Set this to `true` to disable the
/// layer behavior
@mixin styles($disable-layer: false) {
  @if not $disable-everything {
    @include utils.optional-layer(slider, $disable-layer) {
      @include theme.default-system-theme {
        @include use-dark-theme;
      }

      .rmd-slider-container {
        @if $container-addon-spacing and
          $container-addon-spacing !=
          icon.$spacing
        {
          @include icon.set-var(spacing, $container-addon-spacing);
        }

        @include icon.use-var(gap, spacing);

        align-items: center;
        touch-action: none;

        @if not $disable-horizontal {
          &--h {
            display: flex;
            width: 100%;
          }

          &--pad-left {
            padding-left: $container-padding;
          }

          &--pad-right {
            padding-right: $container-padding;
          }
        }

        @if not $disable-vertical {
          &--v {
            display: inline-flex;
            flex-direction: column-reverse;
          }

          &--pad-top {
            padding-top: $container-padding;
          }

          &--pad-bottom {
            padding-bottom: $container-padding;
          }
        }
      }

      .rmd-slider-track {
        position: relative;

        &::before,
        &::after {
          @if $track-color {
            @include use-var(
              background-color,
              color,
              theme.theme-color-var-fallback($track-color)
            );
          }

          content: "";
          pointer-events: none;
          position: absolute;
        }

        &::before {
          @if not $track-color {
            @include use-var(background-color, inactive-color);
          }

          opacity: $track-inactive-opacity;
          z-index: $track-inactive-z-index;
        }

        &::after {
          @if not $track-color {
            @include use-var(background-color, active-color);
          }

          opacity: $track-active-opacity;
          z-index: $track-active-z-index;
        }

        &--hoverable:hover {
          cursor: pointer;
        }

        &--animate::after {
          transition-duration: $transition-duration;
          transition-timing-function: $transition-timing-function;
        }

        @if $track-color {
          &--disabled {
            @include set-var(color, $track-disabled-color);

            @if $track-inactive-opacity {
              &::before {
                opacity: 1;
              }
            }

            &::after {
              @include set-var(active-size, 0px);
              @if $track-active-opacity {
                opacity: 1;
              }
            }
          }
        }

        @if not $disable-horizontal {
          &--h {
            @include use-var(height, size);

            align-items: center;
            display: flex;
            width: 100%;

            &::before {
              @include use-var(height, inactive-size);

              width: 100%;
            }

            &::after {
              @include use-var(height, active-size);
            }
          }

          &--h1::after {
            @include use-var(max-width, offset-1);

            left: 0;
            transition-property: max-width;
            width: 100%;

            @include utils.rtl {
              left: auto;
              right: 0;
            }
          }

          @if not $disable-range {
            &--h2::after {
              left: get-var(offset-1);
              right: calc(100% - get-var(offset-2));
              transition-property: left, right;
              will-change: left, right;

              @include utils.rtl {
                left: calc(100% - get-var(offset-2));
                right: get-var(offset-1);
              }
            }
          }
        }

        @if not $disable-vertical {
          &--v {
            @include use-var(height, vertical-size);
            @include use-var(width, size);

            display: inline-flex;
            justify-content: center;

            &::before {
              @include use-var(width, inactive-size);

              height: 100%;
            }

            &::after {
              @include use-var(width, active-size);

              bottom: 0;
            }
          }

          // one thumb track horizontal styles
          &--v1::after {
            @include use-var(max-height, offset-1);

            height: 100%;
            transition-property: max-height;
          }

          @if not $disable-range {
            // two thumb track horizontal styles
            &--v2::after {
              @include use-var(bottom, offset-1);

              top: calc(100% - #{get-var(offset-2)});
              transition-property: bottom, top;
              will-change: bottom, top;
            }
          }
        }
      }

      .rmd-slider-thumb {
        @include use-var(
          background-color,
          if($track-color, color, active-color),
          if($track-color, theme.theme-color-var-fallback($track-color), null)
        );

        border-radius: $thumb-border-radius;
        height: $thumb-size;
        outline: 0;
        position: absolute;
        width: $thumb-size;
        z-index: $thumb-z-index;

        &::after {
          @include utils.pseudo-element($z-index: null);

          background-color: inherit;
          opacity: $thumb-bubble-opacity;
          transition: transform $transition-duration $transition-timing-function;
        }

        @if utils.$disable-focus-visible {
          @include utils.keyboard-only {
            &:focus::after {
              transform: scale($thumb-focus-scale);
            }
          }
        } @else {
          &:focus-visible::after {
            transform: scale($thumb-focus-scale);
          }
        }

        @include utils.mouse-hover(false) {
          &:hover::after,
          &--active::after,
          &--active:hover::after {
            transform: scale($thumb-active-scale);
          }
        }

        &--animate {
          transition-duration: $transition-duration;
          transition-timing-function: $transition-timing-function;
        }

        &--disabled {
          background-color: $thumb-disabled-color;

          // prevent hover effects like the "bubble"
          pointer-events: none;
        }

        &--mask {
          @include theme.theme-use-var(background-color);

          border-radius: 0;
        }

        @if not $disable-horizontal {
          &--h {
            transform: translateX(-50%);
            transition-property: left;

            @include utils.rtl {
              transform: translateX(50%);
              transition-property: right;
            }
          }

          &--h1 {
            @include use-var(left, offset-1);

            @include utils.rtl {
              @include use-var(right, offset-1);

              left: auto;
            }
          }

          @if not $disable-range {
            &--h2 {
              @include use-var(left, offset-2);

              @include utils.rtl {
                @include use-var(right, offset-2);

                left: auto;
              }
            }
          }

          &--disabled-h {
            transform: translateX(-50%) scale($thumb-disabled-scale);

            @include utils.rtl {
              transform: translateX(50%) scale($thumb-disabled-scale);
            }
          }

          &--mask-h {
            transform: translateX(-50%) scale($thumb-mask-scale);

            @include utils.rtl {
              transform: translateX(50%) scale($thumb-mask-scale);
            }
          }
        }

        @if not $disable-vertical {
          &--v {
            // want the thumb to be aligned so that the center is at the current value.
            // without this transformation, the thumb's bottom side would be aligned
            // with the current value
            transform: translateY(50%);
            transition-property: bottom;
          }

          &--v1 {
            @include use-var(bottom, offset-1);
          }

          @if not $disable-range {
            &--v2 {
              @include use-var(bottom, offset-2);
            }
          }

          &--disabled-v {
            transform: translateY(50%) scale($thumb-disabled-scale);
          }

          &--mask-v {
            transform: translateY(50%) scale($thumb-mask-scale);
          }
        }

        &__input {
          appearance: none;
          height: 0;
          opacity: 0;
          pointer-events: none;
          width: 0;
        }
      }

      @if not $disable-discrete {
        .rmd-slider-tooltip {
          opacity: 1;
          position: absolute;
          z-index: $tooltip-z-index;

          // this is used to generate the triangle
          &::after {
            border: $tooltip-caret-size solid transparent;
            content: "";
            position: absolute;
          }

          &--animate {
            transition: transform
              $transition-duration
              $transition-timing-function;
          }

          @if not $disable-horizontal {
            &--h {
              top: $tooltip-offset;
              transform: translateX(get-var(tooltip-translate))
                scale(get-var(tooltip-scale));

              &::after {
                @include tooltip.use-var(border-top-color, background-color);

                left: 50%;
                top: 100%;
                transform: translateX(get-var(tooltip-translate));
              }

              @include utils.rtl {
                @include set-var(tooltip-translate, 50%);
              }
            }

            &--h-off {
              @include set-var(tooltip-scale, 0);
            }

            // have to "duplicate" these styles since the `--h-off` would override the
            // `--h` styles due to css order.
            &--h-on {
              @include set-var(tooltip-scale, 1);
            }
          }

          @if not $disable-vertical {
            &--v {
              // going to force rendering always to the left even in RTL languages
              left: $tooltip-offset;
              transform: translateY(50%) scale(1);

              &::after {
                @include tooltip.use-var(border-left-color, background-color);

                left: 100%;
                top: 50%;
                transform: translateY(-50%);
              }
            }

            &--v-off {
              transform: translateY(50%) scale(0);
            }

            // have to "duplicate" these styles since the `--v-off` would override the
            // `--v` styles due to css order.
            &--v-on {
              transform: translateY(50%) scale(1);
            }
          }
        }
      }

      @if not $disable-discrete-marks {
        .rmd-slider-mark {
          border-radius: $mark-border-radius;
          position: absolute;

          &--inactive {
            @include use-var(background-color, mark-inactive-color);
            @include use-var(opacity, mark-inactive-opacity);

            z-index: $mark-inactive-z-index;
          }

          &--active {
            @include use-var(background-color, mark-active-color);
            @include use-var(opacity, mark-active-opacity);

            z-index: $mark-active-z-index;
          }

          @if not $disable-horizontal {
            &--h {
              @include use-var(left, mark-offset);

              height: $mark-height;
              top: 50%;
              transform: translateY(-50%);
              width: $mark-width;

              @include utils.rtl {
                @include use-var(right, mark-offset);

                left: auto;
              }
            }
          }

          @if not $disable-vertical {
            &--v {
              @include use-var(bottom, mark-offset);

              height: $mark-width;
              transform: translateY(50%);
              width: $mark-height;
            }
          }
        }
      }

      @if not $disable-discrete-marks-labels {
        .rmd-slider-mark-label {
          position: absolute;

          @if not $disable-horizontal {
            &--h {
              @include use-var(left, mark-offset);

              top: 100%;
              transform: translateX(-50%);

              @include utils.rtl {
                @include use-var(right, mark-offset);

                left: auto;
                transform: translateX(50%);
              }
            }
          }

          @if not $disable-vertical {
            &--v {
              left: 100%;
              top: get-var(mark-offset);
              transform: translateY(-50%);

              @include utils.rtl {
                left: auto;
                right: 100%;
              }
            }
          }
        }
      }
    }
  }
}
